package com.example.supplychainbackend.service.Impl;

import com.example.supplychainbackend.controller.dto.blockchain.UploadInfo;
import com.example.supplychainbackend.controller.dto.purchase.*;
import com.example.supplychainbackend.controller.dto.user.UserSigDto;
import com.example.supplychainbackend.dao.purchase.PurchaseContractDao;
import com.example.supplychainbackend.dao.purchase.PurchaseMaterialDao;
import com.example.supplychainbackend.dao.purchase.PurchaseOrderDao;
import com.example.supplychainbackend.dao.purchase.PurchaseRequireDao;
import com.example.supplychainbackend.entity.purchase.PurchaseContractEntity;
import com.example.supplychainbackend.entity.purchase.PurchaseMaterialEntity;
import com.example.supplychainbackend.entity.purchase.PurchaseOrderEntity;
import com.example.supplychainbackend.entity.purchase.PurchaseRequireEntity;
import com.example.supplychainbackend.mapper.PurchaseMapper;
import com.example.supplychainbackend.service.BlockchainService;
import com.example.supplychainbackend.service.PurchaseService;
import com.example.supplychainbackend.tool.DateTimeUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
@RequiredArgsConstructor
public class PurchaseServiceImpl implements PurchaseService {
    private final PurchaseRequireDao purchaseRequireDao;
    private final PurchaseOrderDao purchaseOrderDao;
    private final PurchaseMaterialDao purchaseMaterialDao;
    private final PurchaseContractDao purchaseContractDao;
    private final PurchaseMapper mapper;

    private final BlockchainService blockchainService;

    @Override
    public String createPurchaseRequire(PurchaseRequireDto dto) {
        PurchaseRequireEntity entity = mapper.toPurchaseRequireEntity(dto);
        //设置id
        entity.setStatus("1");
        entity.setOnChain(false);
        entity.setApplicant(dto.getUserName());
        entity = purchaseRequireDao.save(entity);
        return entity.getPurchaseRequestNumber().toString();
    }

    @Override
    public String reviewPurchaseRequire(String id, Integer status, UserSigDto sigDto) {
        PurchaseRequireEntity entity = purchaseRequireDao.findById(id).get();
        switch (status) {
            case 1 :
                entity.setStatus("2");
                entity.setApprovalStatus(2);
                break;
            case 2:
                entity.setStatus("4");
                entity.setApprovalStatus(4);
                break;
        }
        entity.setRecentApprovalTime(DateTimeUtils.getCurrentDateTime());
        return purchaseRequireDao.save(entity).getPurchaseRequestNumber().toString();
    }

    @Override
    public PurchaseRequireDto updatePurchaseRequire(String id, PurchaseRequireDto dto) {
        PurchaseRequireEntity entity = purchaseRequireDao.findById(id).get();
        /*铸币了，可以修改Mapper设置来完成null的检查
        if(dto.getPurchaseRequestDepartment()!=null)
            entity.setPurchaseRequestDepartment(dto.getPurchaseRequestDepartment());
        if (dto.getPurchaseType()!=null)
            entity.setPurchaseType(dto.getPurchaseType());
        if(dto.getLineNumber()!=null)
            entity.setLineNumber(dto.getLineNumber());
        if(dto.getWorkOrderNumber()!=null)
            entity.setWorkOrderNumber(dto.getWorkOrderNumber());
        if (dto.getPurchaseGroup()!=null)
            entity.setPurchaseGroup(dto.getPurchaseGroup());
        if(dto.getContractName()!=null)
            entity.setContractName(dto.getContractName());
        if(dto.getContractNumber()!=null)
            entity.setContractNumber(dto.getContractNumber());
        if(dto.getSalesOrderName()!=null)
            entity.setSalesOrderName(dto.getSalesOrderName());
        if(dto.getMaterialNumber()!=null)
            entity.setMaterialNumber(dto.getMaterialNumber());
        if(dto.getMaterialName()!=null)
            entity.setMaterialName(dto.getMaterialName());
        if(dto.getMaterialDescription()!=null)
            entity.setMaterialDescription(dto.getMaterialDescription());
        if(dto.getRequiredQuantity()!=null)
            entity.setRequiredQuantity(dto.getRequiredQuantity());*/
        mapper.updateFromDto(entity,dto);
        entity = purchaseRequireDao.save(entity);
        return mapper.toPurchaseRequireDto(entity);
    }

    @Override
    public String deletePurchaseRequire(String id) {
        purchaseRequireDao.deleteById(id);
        return id;
    }

    @Override
    public PurchaseRequireDto getByIdPurchaseRequire(String id) {
        PurchaseRequireEntity entity = purchaseRequireDao.findById(id).get();
        return mapper.toPurchaseRequireDto(entity);
    }

    @Override
    public List<PurchaseRequireDto> getListPurchaseRequire() {
        List<PurchaseRequireEntity> entities = purchaseRequireDao.findAll();
        return mapper.toPurchaseRequireDtoList(entities);
    }
    @Override
    public List<PurchaseRequireDto> getListPurchaseRequireByEid(String eid) {
        List<PurchaseRequireEntity> entities = purchaseRequireDao.findAllByEnterpriseId(eid);
        return mapper.toPurchaseRequireDtoList(entities);
    }

    @Override
    public String createPurchaseOrder(PurchaseOrderDto dto) {
        PurchaseOrderEntity entity = mapper.toPurchaseOrderEntity(dto);
        entity.setOnChain(false);
        for (PurchaseMaterialEntity mat:
             entity.getMaterialList()) {
            mat.setId(null);
        }
        if (entity.getStatus()  == null || 0 == entity.getStatus())
            entity.setStatus(1);
        return purchaseOrderDao.save(entity).getPurchaseOrderNumber().toString();
    }

    @Override
    public PurchaseOrderDto updatePurchaseOrder(String id, PurchaseOrderDto dto) {
        PurchaseOrderEntity entity = purchaseOrderDao.findById(id).get();
        mapper.updateFromDto(entity,dto);
        entity.setPurchaseOrderNumber(id);
        entity = purchaseOrderDao.save(entity);
        return mapper.toPurchaseOrderDto(entity);
    }

    @Override
    public String deletePurchaseOrder(String id) {
        purchaseOrderDao.deleteById(id);
        return id;
    }

    @Override
    public PurchaseOrderDto getByIdPurchaseOrder(String id) {
        PurchaseOrderEntity entity = purchaseOrderDao.findById(id).get();
        return mapper.toPurchaseOrderDto(entity);
    }

    @Override
    public List<PurchaseOrderDto> getListPurchaseOrder() {
        List<PurchaseOrderEntity> entities = purchaseOrderDao.findAll();
        return mapper.toPurchaseOrderDtoList(entities);
    }
    @Override
    public List<PurchaseOrderDto> getListPurchaseOrderByEid(String eid) {
        List<PurchaseOrderEntity> entities = purchaseOrderDao.findAllByEnterpriseId(eid);
        return mapper.toPurchaseOrderDtoList(entities);
    }

    @Override
    public String createPurchaseMaterial(PurchaseMaterialDto dto) {
        PurchaseMaterialEntity entity = mapper.toPurchaseMaterialEntity(dto);
        entity = purchaseMaterialDao.save(entity);
        return entity.getLineNumber().toString();
    }

    @Override
    public PurchaseMaterialDto updatePurchaseMaterial(String id, PurchaseMaterialDto dto) {
        PurchaseMaterialEntity entity = purchaseMaterialDao.findById(Long.parseLong(id)).get();
        mapper.updateFromDto(entity,dto);
        entity.setLineNumber(id);
        entity = purchaseMaterialDao.save(entity);
        return mapper.toPurchaseMaterialDto(entity);
    }

    @Override
    public String deletePurchaseMaterial(String id) {
        purchaseMaterialDao.deleteById(Long.parseLong(id));
        return id;
    }

    @Override
    public PurchaseMaterialDto getByIdPurchaseMaterial(String id) {
        PurchaseMaterialEntity entity = purchaseMaterialDao.findById(Long.parseLong(id)).get();
        return mapper.toPurchaseMaterialDto(entity);
    }

    @Override
    public List<PurchaseMaterialDto> getListPurchaseMaterial() {
        List<PurchaseMaterialEntity> entities = purchaseMaterialDao.findAll();
        return mapper.toPurchaseMaterialDtoList(entities);
    }

    @Override
    public String createPurchaseContract(PurchaseContractDto dto) {
        PurchaseContractEntity entity = mapper.toPurchaseContractEntity(dto);
        entity = purchaseContractDao.save(entity);
        return mapper.toPurchaseContractDto(entity).getContractNo();
    }

    @Override
    public PurchaseContractDto updatePurchaseContract(String id, PurchaseContractDto dto) {
        PurchaseContractEntity entity = purchaseContractDao.findById(Long.parseLong(id)).get();
        mapper.updateFromDto(entity,dto);
        entity.setContractNo(id);
        entity = purchaseContractDao.save(entity);
        return mapper.toPurchaseContractDto(entity);
    }

    @Override
    public String deletePurchaseContract(String id) {
        purchaseContractDao.deleteById(Long.parseLong(id));
        return id;
    }

    @Override
    public PurchaseContractDto getByIdPurchaseContract(String id) {
        PurchaseContractEntity entity = purchaseContractDao.findById(Long.parseLong(id)).get();
        return mapper.toPurchaseContractDto(entity);
    }

    @Override
    public PurchaseContractListDto getListPurchaseContract() {
        List<PurchaseContractEntity> contractEntities = purchaseContractDao.findAll();
        List<PurchaseOrderEntity> orderEntities = purchaseOrderDao.findAll();
        return new PurchaseContractListDto(mapper.toPurchaseContractPODtoList(orderEntities),mapper.toPurchaseContractDtoList(contractEntities));
    }

    @Override
    public UploadInfo uploadToChainOrder(String id) {
        PurchaseOrderDto purchaseOrder = this.getByIdPurchaseOrder(id);
        if (null!=purchaseOrder){
            UploadInfo txInfo = blockchainService.uploadPurchaseOrder("PurchaseOrder"+id, purchaseOrder.toString());
            purchaseOrder.setOnChain(true);
            purchaseOrder.setCommitTime(txInfo.getCommitTime());
            purchaseOrder.setTransactionId(txInfo.getTransactionId());
            purchaseOrderDao.save(mapper.toPurchaseOrderEntity(purchaseOrder));
            return txInfo;
        }
        throw new RuntimeException("purchase order not found");
    }

    @Override
    public UploadInfo uploadToChainRequire(String id) {
        PurchaseRequireDto purchaseRequire = this.getByIdPurchaseRequire(id);
        if (null!=purchaseRequire){
            if (!purchaseRequire.getStatus().equals("2"))
                throw new RuntimeException("PR not reviewed");
            UploadInfo txInfo = blockchainService.uploadPurchaseReq(id, purchaseRequire.toString());
            purchaseRequire.setOnChain(true);
            purchaseRequire.setCommitTime(txInfo.getCommitTime());
            purchaseRequire.setTransactionId(txInfo.getTransactionId());
            purchaseRequireDao.save(mapper.toPurchaseRequireEntity(purchaseRequire));
            return txInfo;
        }
        throw new RuntimeException("require not found");
    }
}
